package entity

import (
	"fmt"
	"src/protoMsg"
	"src/zeus/bytestream"
	"src/zeus/iserver"
	"src/zeus/logger"
	"src/zeus/msgdef"
)

// InitProp 初始化属性列表
func (e *Entity) InitProp(def *Def, interestSrvType uint8, subType string) {
	e.IPropsContainer.InitProp(def, interestSrvType, subType)
	// e.realPtr.ReflushFromDB()
}

// // ReflushDirtyProp 每一帧刷新属性通知
// func (e *Entity) ReflushDirtyProp() {
// 	// e.dirtyClientMsg = nil
// 	e.realPtr.ReflushSync()
// 	// e.realPtr.ReflushToDB()
// }

// 打包自己关心的脏属性
func (e *Entity) PackMRoleDirtyProps() (result *protoMsg.PropBaseSyncList) {
	return e.GetDirtyMRoleMsg()
	// result = PackPropsToProtobuf(e.dirtyMRoleProps)
	// return result
}

// 同步自己的数据到别的服务器上去（对方服务器需要的所有字段）
func (e *Entity) SyncDataToOtherServer(srvtype uint8) {
	m := make([]*PropInfo, 0, 10)
	/*
		只会把目标服务器需要，本服务器有的数据；
		同时不是在目标服务器上进行持久化的数；
	*/
	e.ForEachProp(func(p *PropInfo) {
		for _, s := range p.Def.InterestSrvs {
			if s == srvtype && e.isEntityExisted(s) &&
				p.Def.SaveSrvType != srvtype &&
				p.Def.MainSrvType != srvtype {
				m = append(m, p)
			}
		}
	})
	if err := e.Post(srvtype, &msgdef.PropsSync{Num: uint32(len(m)), Data: e.PackPropsToBytes(m)}); err != nil {
		e.Error("Send PropsSync failed ", err)
	}
}

// 同步自己的脏数据到别的服务器上去，也发给客户端等
func (e *Entity) ReflushSync() {
	e.PackPropsSyncProps()

	// e.HandlerSorterResultForeach(EDPSorterTypeSync, func(p *PropInfo) {
	// 	for _, s := range p.Def.InterestSrvs {
	// 		if s != iserver.GetSrvInst().GetSrvType() && e.isEntityExisted(s) {
	// 			m := e.getDirtyProps(s)
	// 			e.dirtyProps[s] = append(m, p)
	// 		}
	// 	}
	// })
	// 	if p.Def.IsClientInterest {
	// 		e.dirtyClientProps = append(e.dirtyClientProps, p)
	// 	}
	// 	if p.Def.IsMRoleInterest {
	// 		e.dirtyMRoleProps = append(e.dirtyMRoleProps, p)
	// 	}
	// })

	e.sendPropsSyncMsg()
}

func (e *Entity) sendPropsSyncMsg() {
	//发数据给其他服务器
	for s, m := range e.DirtySrvProps {
		if len(m) != 0 {
			e.DirtySrvProps[s] = e.DirtySrvProps[s][0:0]
			if !e.isEntityExisted(s) {
				continue
			} else if err := e.Post(s, &msgdef.PropsSync{Num: uint32(len(m)), Data: e.PackPropsToBytes(m)}); err != nil {
				e.Error("Send PropsSync failed ", err)
			}
		}
	}
	real := e.GetRealPtr().(IEntityReal)
	if prolist := real.PackMRoleDirtyProps(); prolist != nil && len(prolist.Prop) != 0 {
		msg := &protoMsg.PropSyncList{
			EntityID:   e.GetID(),
			EntityType: e.GetType(),
			Prop:       prolist,
		}
		e.Post(iserver.ServerTypeClient, msg)
		// e.dirtyMRoleProps = e.dirtyMRoleProps[0:0]
	}
}

// ReflushFromMsg 从消息中更新属性
func (e *Entity) ReflushFromMsg(num int, data []byte) {
	bs := bytestream.NewByteStream(data)
	for i := 0; i < num; i++ {
		if _, err := e.realPtr.ReflushPropFromMsg(bs); err != nil {
			logger.Error("ReflushFromMsg ", err)
		}
	}
}

// 单个字段刷新
func (e *Entity) ReflushPropFromMsg(bs *bytestream.ByteStream) (index uint16, err error) {
	index, err = bs.ReadUInt16()
	if err != nil {
		return
	}
	prop := e.GetPropRaw2(index)
	if prop == nil {
		err = fmt.Errorf("target entity not own prop %d;", index)
		return
	}
	/*
		因为entity的保存逻辑只会在一个服务器上使用，
		所以别的服务器上数据同步过来的时候，需要进行保存数据的标脏
	*/
	prop.props.PropDirty2(prop.GetIndex(), int8(EDPSorterTypeSave))
	err = prop.ReadValueFromStream(bs)
	if err != nil {
		return
	}
	/*
		如果收到别的服务器的的同步信息，需要通知给客户端
	*/
	if prop.Def.IsClientInterest {
		// e.PropDirty2(prop.GetIndex(), int8(EDPSorterTypeSync))
		e.dirtyAOIProps = append(e.dirtyAOIProps, prop)
	}
	if prop.Def.IsMRoleInterest { //fixed
		//非自己管理的属性 是不需要发送给自己的客户端的.
		if !(prop.Def.SaveSrvType == iserver.GetSrvInst().GetSaveType() ||
			prop.Def.MainSrvType == iserver.GetSrvInst().GetSaveType()) {
			logger.Debug(logger.LogKey_Prop, " 非本服务器 关心属性,不要给客户端下发属性.", prop)
			return
		}
		if prop.Def.Name == "PlayerGuildInfo" { //fixed log
			logger.Debug(logger.LogKey_Prop, "PlayerGuildInfo 本服务器 关心属性,给客户端下发属性.", prop)
		}
		// e.PropDirty2(prop.GetIndex(), int8(EDPSorterTypeSync))
		e.dirtyMRoleProps = append(e.dirtyMRoleProps, prop)
	}
	return
}

// PackMRoleProps 打包主角关心的属性
func (e *Entity) PackMRoleProps() msgdef.IMsg {
	props := make([]*PropInfo, 0, 10)
	e.ForEachProp(func(prop *PropInfo) {
		if prop.Def.IsMRoleInterest { //fixed
			//非自己管理的属性 是不需要发送给自己的客户端的.
			if !(prop.Def.SaveSrvType == iserver.GetSrvInst().GetSaveType() ||
				prop.Def.MainSrvType == iserver.GetSrvInst().GetSaveType()) {
				logger.Debug(logger.LogKey_Prop, "非本服务器 关心属性,不要给客户端下发属性.", prop)
				return
			}
			if prop.Def.Name == "PlayerGuildInfo" { //fixed log
				logger.Debug(logger.LogKey_Prop, "PlayerGuildInfo 本服务器 关心属性,给客户端下发属性.", prop)
			}

			props = append(props, prop)
		}
	})

	prolist := PackPropsToProtobuf(props)
	// msg := &protoMsg.PlayerPropSyncList{
	// 	EntityID: e.GetID(),
	// 	Prop:     prolist.(*protoMsg.PropBaseSyncList),
	// }
	return prolist
}

// PackPropsToBytes 把属列表打包成bytes
func (e *Entity) PackPropsToBytes(props []*PropInfo) []byte {
	size := 0

	for _, prop := range props {
		size = size + 2 // 2 index所占大小
		size = size + prop.GetValueStreamSize()
	}

	if size == 0 {
		return nil
	}

	buf := make([]byte, size)
	bs := bytestream.NewByteStream(buf)

	for _, prop := range props {
		if err := bs.WriteUInt16(prop.Def.Index); err != nil {
			e.Error("Pack props failed ", err, prop.Def.Name)
		}
		if err := prop.WriteValueToStream(bs); err != nil {
			e.Error("Pack props failed ", err, prop.Def.Name)
		}
	}

	return buf
}
